#include <iostream>
#include <memory>
#include <string>
/*简单工厂模式：不符合开闭原则*/

class Fruit
{
public:
    /*必须是一个纯虚函数，让子类必须重写这个虚函数*/
    virtual void name() = 0;
};
class Apple : public Fruit
{
public:
    void name() override
    {
        std::cout << "我是一个苹果！" << std::endl;
    }
};

class Banana : public Fruit
{
public:
    void name() override
    {
        std::cout << "我是一个香蕉！" << std::endl;
    }
};
// class FruitFactory
// {
// public:
//     static std::shared_ptr<Fruit> create(const std::string &str)
//     {
//         if (str == "苹果")
//         {
//             return std::make_shared<Apple>();
//         }
//         else
//         {
//             return std::make_shared<Banana>();
//         }
//     }
// };


class Animal
{
public:
    virtual void name() = 0;
};
class Cat : public Animal
{
public:
    void name() override
    {
        std::cout << "我是一只小猫！" << std::endl;
    }
};
class Dog : public Animal
{
public:
    void name() override
    {
        std::cout << "我是一只小狗！" << std::endl;
    }
};

/*抽象工厂模式：让一个工厂类派生出不同类型的工厂，然后不同类型的工厂生产出不同的产品*/
class Factory
{
public:
    virtual std::shared_ptr<Fruit> getFruit(const std::string &str) = 0;
    virtual std::shared_ptr<Animal> getAnimal(const std::string &str) = 0;
};
class FruitFactory : public Factory
{
public:
    std::shared_ptr<Fruit> getFruit(const std::string &str)
    {
        if (str == "苹果")
        {
            return std::make_shared<Apple>();
        }
        else
        {
            return std::make_shared<Banana>();
        }
    }
    std::shared_ptr<Animal> getAnimal(const std::string &str)
    {
        return std::shared_ptr<Animal>();
    }
};
class AnimalFactory : public Factory
{
public:
    std::shared_ptr<Animal> getAnimal(const std::string &str)
    {
        if (str == "小猫")
        {
            return std::make_shared<Cat>();
        }
        else
        {
            return std::make_shared<Dog>();
        }
    }
    std::shared_ptr<Fruit> getFruit(const std::string &str)
    {
        return std::shared_ptr<Fruit>();
    }
};
class FactoryProducer
{
public:
    static std::shared_ptr<Factory> create(const std::string &str)
    {
        if (str == "水果")
        {
            return std::make_shared<FruitFactory>();
        }
        else
        {
            return std::make_shared<AnimalFactory>();
        }
    }
};

/*工厂方法模式：符合开闭原则，一个产品对应一个工厂，一个工厂只生产一种产品*/
// class FruitFactory
// {
// public:
//     virtual std::shared_ptr<Fruit> create() = 0;
// };
// class AppleFactory : public FruitFactory
// {
// public:
//     std::shared_ptr<Fruit> create() override
//     {
//         return std::make_shared<Apple>();
//     }
// };

// class BananaFactory : public FruitFactory
// {
// public:
//     std::shared_ptr<Fruit> create() override
//     {
//         return std::make_shared<Banana>();
//     }
// };

int main()
{
    //抽象工厂模式
    // 1、先生产一个水果工厂
    std::shared_ptr<Factory> ff = FactoryProducer::create("水果");
    // 2、再让水果工厂生产水果
    std::shared_ptr<Fruit> fruit = ff->getFruit("苹果");
    fruit->name();
    fruit = ff->getFruit("香蕉");
    fruit->name();

    // 1、先生产一个动物工厂
    std::shared_ptr<Factory> factory = FactoryProducer::create("动物");
    // 2、再让动物工厂生产动物
    std::shared_ptr<Animal> animal = factory->getAnimal("小猫");
    animal->name();
    animal = factory->getAnimal("小狗");

    //判断管理对象是否为空，增加代码的健壮性
    if(animal.get()==nullptr)
    {
        return 0;
    }
    animal->name();

    //工厂方法模式
    // std::shared_ptr<FruitFactory> ff(new AppleFactory());
    // std::shared_ptr<Fruit> fruit = ff->create();
    // fruit->name();

    // ff.reset(new BananaFactory());
    // fruit = ff->create();
    // fruit->name();

    //简单工厂模式
    // std::shared_ptr<Fruit> fruit = FruitFactory::create("苹果");
    // fruit->name();
    // fruit = FruitFactory::create("香蕉");
    // fruit->name();

    return 0;
}